home *** CD-ROM | disk | FTP | other *** search
- #!/usr/bin/perl -w
- #
- # $Id: NetworkTree.pm,v 1.92 2005/04/11 21:58:28 solovam Exp $
- #
- # This file is a part of gkismet
- #
- # This program is free software; you can redistribute it and/or
- # modify it under the terms of the GNU General Public License
- # as published by the Free Software Foundation; either version 2
- # of the License, or (at your option) any later version.
- #
- # This program is distributed in the hope that it will be useful,
- # but WITHOUT ANY WARRANTY; without even the implied warranty of
- # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- # GNU General Public License for more details.
- #
- # You should have received a copy of the GNU General Public License
- # along with this program; if not, write to the Free Software
- # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- #
-
- #
- # NetworkTree class
- #
- package NetworkTree;
-
- use Gtk;
- use strict;
- use Misc;
- use Observable;
- use ReusableConnObserver;
-
- @NetworkTree::ISA = qw(Observable ReusableConnObserver);
-
- my %network_type = (network_ap => 0, network_adhoc => 1, network_probe => 2, network_turbocell => 3, network_data => 4, network_remove => 5);
- my %address_type = (address_none => 0, address_factory => 1, address_udp => 2, address_arp => 3, address_tcp => 4, address_dhcp => 5, address_group => 6);
- my %carrier_type = (carrier_unknown => 0, carrier_80211b => 1, carrier_80211bplus => 2, carrier_80211a => 3, carrier_80211g => 4,
- carrier_80211fhss => 5, carrier_80211dsss => 6);
- my %client_type = (client_unknown => 0, client_fromds => 1, client_tods => 2, client_interds => 3, client_established => 4);
- my %encoding_type = (encoding_unknown => 0, encoding_cck => 1, encoding_pbcc => 2, encoding_ofdm => 3);
- my %encryption_type = (encryption_none => 0, encryption_unknown => 1, encryption_wep => 2, encryption_layer3 => 4, encryption_wpa => 64,
- encryption_leap => 128, encryption_ttls => 256, encryption_tls => 512, encryption_peap => 1024, encryption_isakmp => 2048, encryption_pptp => 4096);
- my $max_manuf_score = 8;
- my $timerTimeout = 1000;
- my $activeTimeout = 5;
- my %networkFieldType = (channel => 'num', firsttime => 'num', lasttime => 'num', datapackets => 'num', signal => 'num', bssid => 'str',
- ssid => 'str', wep => 'str');
- my %clientFieldType = (firsttime => 'num', lasttime => 'num', datapackets => 'num', signal => 'num', mac => 'str', wep => 'str');
-
- #
- # Constructor
- #
- sub new
- {
- my $type = shift;
- my $self = new ReusableConnObserver(@_);
- bless $self, $type;
-
- # Create ctree
- $self->{'ctree'} = new Gtk::CTree(3, 0);
- $self->{'ctree'}->set_column_auto_resize(0, $true);
- $self->{'ctree'}->set_column_auto_resize(1, $true);
- $self->{'ctree'}->set_line_style('dotted');
- $self->{'ctree'}->set_indent(15);
- $self->{'ctree'}->set_spacing(5);
- $self->{'ctree'}->set_selection_mode(1);
- $self->{'ctree'}->set_column_visibility(2, $false);
- $self->{'ctree'}->set_sort_column(2);
- $self->{'ctree'}->set_compare_func(sub {$self->compare(@_)});
- $self->{'ctree'}->signal_connect('tree_select_row', sub {$self->selectHandler(@_)});
- $self->{'ctree'}->signal_connect('tree_unselect_row', sub {$self->selectHandler(@_)});
- $self->{'ctree'}->show();
-
- # Read manufacturers data
- $self->{'apManuf'} = $self->readManufData($self->{'gKismetApplication'}{'path'}{'etc'} . '/ap_manuf');
- $self->{'clManuf'} = $self->readManufData($self->{'gKismetApplication'}{'path'}{'etc'} . '/client_manuf');
-
- # Get colors
- $self->buildColors();
-
- # Ask to notify us of the preferences changes
- $self->{'gKismetApplication'}->{'preferences'}->addObserver($self);
-
- # Popup menu
- my @menuItems =
- (
- {path => '/Expand', callback => sub {$self->expand()}},
- {path => '/Collapse', callback => sub {$self->collapse()} },
- {path => '/Packet Dump', callback => sub {$self->{'gKismetApplication'}->bssObserverOpenSelected('PacketWindow')}},
- {path => '/String Dump', callback => sub {$self->{'gKismetApplication'}->bssObserverOpenSelected('StringWindow')}},
- {path => '/Locator', callback => sub {$self->{'gKismetApplication'}->bssObserverOpenSelected('Locator')}},
- {path => '/Sort', type => '<Branch>'},
- {path => '/Sort/Ascending', callback => sub {$self->setSortOrder('ascending')}},
- {path => '/Sort/Descending', callback => sub {$self->setSortOrder('descending')}},
- {path => '/Sort Networks', type => '<Branch>'},
- {path => '/Sort Networks/By channel', callback => sub {$self->setNetworksSortBy('channel')}},
- {path => '/Sort Networks/By first seen', callback => sub {$self->setNetworksSortBy('firsttime')}},
- {path => '/Sort Networks/By last seen', callback => sub {$self->setNetworksSortBy('lasttime')}},
- {path => '/Sort Networks/By BSSID', callback => sub {$self->setNetworksSortBy('bssid')}},
- {path => '/Sort Networks/By SSID', callback => sub {$self->setNetworksSortBy('ssid')}},
- {path => '/Sort Networks/By data packet count', callback => sub {$self->setNetworksSortBy('datapackets')}},
- {path => '/Sort Networks/By signal power', callback => sub {$self->setNetworksSortBy('signal')}},
- {path => '/Sort Networks/By WEP', callback => sub {$self->setNetworksSortBy('wep')}},
- {path => '/Sort Clients', type => '<Branch>'},
- {path => '/Sort Clients/By first seen', callback => sub {$self->setClientsSortBy('firsttime')}},
- {path => '/Sort Clients/By last seen', callback => sub {$self->setClientsSortBy('lasttime')}},
- {path => '/Sort Clients/By MAC', callback => sub {$self->setClientsSortBy('mac')}},
- {path => '/Sort Clients/By data packet count', callback => sub {$self->setClientsSortBy('datapackets')}},
- {path => '/Sort Clients/By signal power', callback => sub {$self->setClientsSortBy('signal')}},
- {path => '/Sort Clients/By WEP', callback => sub {$self->setClientsSortBy('wep')}},
- );
- my $accelGroup = new Gtk::AccelGroup();
- my $itemFactory = new Gtk::ItemFactory('Gtk::Menu', '<main>', $accelGroup);
- $itemFactory->create_items(@menuItems);
- my $popup = $itemFactory->get_widget('<main>');
- $popup->show_all();
- $self->{'popup'} = $popup;
- $self->{'ctree'}->signal_connect('button_press_event', sub {$self->buttonPressHandler(@_)});
-
- # Sorting
- $self->{'ctree'}->set_sort_type(0);
- $self->{'networksSortBy'} = 'firsttime';
- $self->{'clientsSortBy'} = 'firsttime';
-
- # Set timer
- Gtk->timeout_add($timerTimeout, sub {$self->timerHandler()});
-
- # Pixmaps
- $self->{'pixmapsBuilt'} = $false;
-
- # Standard
- return $self;
- }
-
- #
- # Set sorting order
- #
- sub setSortOrder
- {
- my $self = shift;
- my $order = shift;
- if($order eq 'ascending')
- {
- $self->{'ctree'}->set_sort_type(0);
- }
- else
- {
- $self->{'ctree'}->set_sort_type(1);
- }
- $self->{'ctree'}->freeze();
- $self->{'ctree'}->sort_recursive(undef);
- $self->{'ctree'}->thaw();
- }
-
- #
- # Handle tinmer event
- #
- sub timerHandler
- {
- my $self = shift;
-
- if(!defined $self->{'connection'})
- {
- return $true;
- }
-
- $self->{'ctree'}->freeze();
- for my $bssid (keys %{$self->{'cnode'}})
- {
- my @info = $self->{'ctree'}->get_node_info($self->{'cnode'}{$bssid}{'node'});
- $self->{'ctree'}->set_node_info($self->{'cnode'}{$bssid}{'node'},
- $self->getNetworkFieldValue($bssid, 'SSID'), 5,
- $self->{'pixmap'}{$self->getNetworkPixmapName($bssid)}{'pixmap'},
- $self->{'pixmap'}{$self->getNetworkPixmapName($bssid)}{'mask'},
- $self->{'pixmap'}{$self->getNetworkPixmapName($bssid)}{'pixmap'},
- $self->{'pixmap'}{$self->getNetworkPixmapName($bssid)}{'mask'},
- $false, $info[7]);
- $self->{'ctree'}->node_set_foreground($self->{'cnode'}{$bssid}{'node'}, $self->getNetworkColor($bssid));
- for my $mac (keys %{$self->{'cnode'}{$bssid}{'client'}})
- {
- my @info = $self->{'ctree'}->get_node_info($self->{'cnode'}{$bssid}{'client'}{$mac}{'node'});
- $self->{'ctree'}->set_node_info($self->{'cnode'}{$bssid}{'client'}{$mac}{'node'},
- $self->getClientFieldValue($bssid, $mac, 'MAC'), 5,
- $self->{'pixmap'}{$self->getClientPixmapName($bssid, $mac)}{'pixmap'},
- $self->{'pixmap'}{$self->getClientPixmapName($bssid, $mac)}{'mask'},
- $self->{'pixmap'}{$self->getClientPixmapName($bssid, $mac)}{'pixmap'},
- $self->{'pixmap'}{$self->getClientPixmapName($bssid, $mac)}{'mask'},
- $false, $info[7]);
- }
- }
- if($self->{'gKismetApplication'}{'preferences'}->getPref('keepSorted'))
- {
- $self->sortUpdated();
- }
- $self->{'ctree'}->thaw();
- return $true;
- }
-
- #
- # Sort updated items in ctree
- #
- sub sortUpdated
- {
- my $self = shift;
-
- if(!defined $self->{'connection'})
- {
- return;
- }
-
- if($self->{'networkUpdateFlag'})
- {
- $self->{'ctree'}->sort(undef);
- }
- $self->{'networkUpdateFlag'} = $false;
-
- for my $bssid (keys %{$self->{'cnode'}})
- {
- if($self->{'clientUpdateFlag'}{$bssid})
- {
- $self->{'ctree'}->sort($self->{'cnode'}{$bssid}{'node'});
- }
- $self->{'clientUpdateFlag'}{$bssid} = $false;
- }
- }
-
- #
- # Change network sorting
- #
- sub setNetworksSortBy
- {
- my $self = shift;
- my $networksSortBy = shift;
- $self->{'ctree'}->freeze();
- $self->{'networksSortBy'} = $networksSortBy;
- $self->{'ctree'}->sort_recursive(undef);
- $self->{'ctree'}->thaw();
- }
-
- #
- # Change client sorting
- #
- sub setClientsSortBy
- {
- my $self = shift;
- my $clientsSortBy = shift;
- $self->{'ctree'}->freeze();
- $self->{'clientsSortBy'} = $clientsSortBy;
- $self->{'ctree'}->sort_recursive(undef);
- $self->{'ctree'}->thaw();
- }
-
- #
- # Handle selection changes
- #
- sub selectHandler
- {
- my $self = shift;
- $self->notifyObservers({'changed' => 'selection'});
- }
-
- #
- # Comparison function for CTree
- #
- sub compare
- {
- my $self = shift;
- my $ctree = shift;
- my $text1= shift;
- my $text2 = shift;
-
- if(!defined $self->{'connection'})
- {
- return 0;
- }
-
- my $network = $self->{'connection'}->getNetwork();
-
- my($nodeType1, $bssid1, $mac1) = split /,/, $text1;
- my($nodeType2, $bssid2, $mac2) = split /,/, $text2;
-
- if($nodeType1 eq 'networkNode' && $nodeType2 eq 'networkNode')
- {
- if($networkFieldType{$self->{'networksSortBy'}} eq 'num')
- {
- return $network->{$bssid1}{$self->{'networksSortBy'}} <=> $network->{$bssid2}{$self->{'networksSortBy'}};
- }
- elsif($networkFieldType{$self->{'networksSortBy'}} eq 'str')
- {
- return $network->{$bssid1}{$self->{'networksSortBy'}} cmp $network->{$bssid2}{$self->{'networksSortBy'}};
- }
- }
- elsif ($nodeType1 eq 'clientNode' && $nodeType2 eq 'clientNode')
- {
- if($clientFieldType{$self->{'clientsSortBy'}} eq 'num')
- {
- return $network->{$bssid1}{'client'}{$mac1}{$self->{'clientsSortBy'}} <=> $network->{$bssid2}{'client'}{$mac2}{$self->{'clientsSortBy'}};
- }
- elsif($clientFieldType{$self->{'clientsSortBy'}} eq 'str')
- {
- return $network->{$bssid1}{'client'}{$mac1}{$self->{'clientsSortBy'}} cmp $network->{$bssid2}{'client'}{$mac2}{$self->{'clientsSortBy'}};
- }
- }
-
- return 0;
- }
-
- #
- # Button press handler
- #
- sub buttonPressHandler
- {
- my $self = shift;
- my $ctree = shift;
- my $event = shift;
-
- if($event->{'button'} == 3)
- {
- my($row, $column) = $ctree->get_selection_info($event->{'x'}, $event->{'y'});
- if(defined $row && defined $column)
- {
- $ctree->select_row($row, $column);
- $self->{'popup'}->popup(undef, undef, $event->{'time'}, $event->{'button'}, undef, undef);
- return $true;
- }
- }
- return $false;
- }
-
- #
- # Read manufacturers data from files
- #
- sub readManufData
- {
- my $self = shift;
- my $file = shift;
- my @manuf;
- my @fieldNames = qw(mac mask name model ssid chan ip);
-
- open(FILE, $file) or die "Can't open $file: $!\n";
- while(<FILE>)
- {
- chomp;
- my @fields = split '\t', $_;
- splice(@fields, 0, 1, split '\/', $fields[0]);
- my %m;
- for(my $i = 0; $i <= $#fields; $i++)
- {
- $m{$fieldNames[$i]} = $fields[$i];
- }
- push @manuf, \%m;
- }
- close(FILE);
- return(\@manuf);
- }
-
- #
- # Lookup manufacturer. Very messy.
- #
- sub lookupManuf
- {
- my $self = shift;
- my($manufData, $mac, $ssid, $chan, $wep, $cloaked, $ip) = (@_);
-
- # Is it cached?
- if(defined $self->{'manufLookupCache'}{$manufData}{$mac}{$ssid}{$chan}{$wep}{$cloaked}{$ip})
- {
- return($self->{'manufLookupCache'}{$manufData}{$mac}{$ssid}{$chan}{$wep}{$cloaked}{$ip}{'name'},
- $self->{'manufLookupCache'}{$manufData}{$mac}{$ssid}{$chan}{$wep}{$cloaked}{$ip}{'model'},
- $self->{'manufLookupCache'}{$manufData}{$mac}{$ssid}{$chan}{$wep}{$cloaked}{$ip}{'score'})
- }
-
- # First build list of matching entries
- my @matching;
- my $bestMaskLen = 0;
- for my $m (@{$manufData})
- {
- if($self->macAnd($m->{'mask'}, $mac) eq $m->{'mac'})
- {
- my $maskLen = $self->maskLen($m->{'mask'});
- if($maskLen > $bestMaskLen)
- {
- $bestMaskLen = $maskLen;
- @matching = ();
- }
- push @matching, $m;
- }
- }
-
- # If no matches, return unknowns
- if($#matching < 0)
- {
- $self->{'manufLookupCache'}{$manufData}{$mac}{$ssid}{$chan}{$wep}{$cloaked}{$ip} = {name => 'Unknown', model => 'Unknown', score => 0};
- return('Unknown', 'Unknown', 0);
- }
-
- # Select matches where ssid and channel match
- my $bestScore = 5;
- my $bestMatch = $matching[0];
- for my $m (@matching)
- {
- my $score = 5;
- if(defined $m->{'ssid'} && $m->{'ssid'} eq $ssid)
- {
- $score += 1;
- }
- if(defined $m->{'chan'} && $m->{'chan'} == $chan)
- {
- $score += 1;
- }
- if(defined $m->{'ip'} && $m->{'ip'} eq $ip)
- {
- $score += 1;
- }
- if($score > $bestScore)
- {
- $bestMatch = $m;
- }
- $bestScore = $score;
- }
-
- # Reduce score if wep of cloaking present
- if($bestMatch->{'wep'})
- {
- $bestScore -= 1;
- }
- if($bestMatch->{'cloaked'})
- {
- $bestScore -= 1;
- }
-
- # Update cache
- $self->{'manufLookupCache'}{$manufData}{$mac}{$ssid}{$chan}{$wep}{$cloaked}{$ip} = {name => $bestMatch->{'name'},
- model => $bestMatch->{'model'}, score => $bestScore};
-
- return($bestMatch->{'name'}, $bestMatch->{'model'}, $bestScore);
- }
-
- #
- # Perform logical "and" on MACs
- #
- sub macAnd
- {
- my $self = shift;
- my($a, $b) = (@_);
- my @aOctets = split(':', $a);
- my @bOctets = split(':', $b);
- my @resOctets;
- for(my $i = 0; $i <= 5; $i++)
- {
- $resOctets[$i] = sprintf("%.2X", hex($aOctets[$i]) & hex($bOctets[$i]));
- }
- my $res = join ':', @resOctets;
- return $res;
- }
-
- #
- # Get netmask length
- #
- sub maskLen
- {
- my $self = shift;
- my $mask = shift;
- my @octets = split(':', $mask);
- my $len = 0;
- for(my $i = 0; $i <= 5; $i++)
- {
- my $octet = hex($octets[$i]);
- for(my $j = 0; $j <= 7; $j++)
- {
- if(!$octet)
- {
- return($len);
- }
- $octet = ($octet << 1);
- $len++;
- }
- }
- }
-
- #
- # Remove all stored data
- #
- sub flush
- {
- my $self = shift;
-
- # Remove all nodes from Ctree
- $self->{'ctree'}->freeze();
- for my $n (keys %{$self->{'cnode'}})
- {
- if(defined $self->{'cnode'}{$n}{'node'})
- {
- $self->{'ctree'}->remove_node($self->{'cnode'}{$n}{'node'});
- }
- }
- $self->{'ctree'}->thaw();
-
- # Delete cnodes hash
- delete $self->{'cnode'};
- }
-
- #
- # Get widget
- #
- sub getWidget
- {
- my $self = shift;
- return $self->{'ctree'};
- }
-
- #
- # Handle an update from an observer
- #
- sub update
- {
- my $self = shift;
- my $object = shift;
- my $data = shift;
-
- if($object->isa('Connection') && defined $self->{'connection'} && $object eq $self->{'connection'})
- {
- if($data->{'changed'} eq 'network')
- {
- my $bssid = $data->{'bssid'};
- $self->{'networkUpdateFlag'} = $true;
- $self->networkScreenUpdate($bssid);
- }
- elsif($data->{'changed'} eq 'client')
- {
- my $bssid = $data->{'bssid'};
- my $mac = $data->{'mac'};
- $self->{'clientUpdateFlag'}{$bssid} = $true;
- $self->clientScreenUpdate($bssid, $mac);
- }
- elsif($data->{'changed'} eq 'remove')
- {
- my $bssid = $data->{'bssid'};
- $self->networkScreenRemove($bssid);
- }
- }
- elsif($object->isa('Preferences') && defined $self->{'connection'})
- {
- my $network = $self->{'connection'}->getNetwork();
- $self->{'ctree'}->freeze();
- $self->flush();
- for my $bssid (keys %{$network})
- {
- $self->networkScreenUpdate($bssid);
- for my $mac (keys %{$network->{$bssid}{'client'}})
- {
- $self->clientScreenUpdate($bssid, $mac);
- }
- }
- $self->{'ctree'}->sort_recursive(undef);
- $self->{'ctree'}->thaw();
- }
- }
-
- #
- # Network is updated or added
- #
- sub networkScreenUpdate
- {
- my $self = shift;
- my $bssid = shift;
-
- if(!defined $self->{'connection'})
- {
- return;
- }
-
- $self->{'ctree'}->freeze();
-
- # If there is no network node create it
- if(!defined $self->{'cnode'}{$bssid}{'node'})
- {
- my $n = $self->{'ctree'}->insert_node(undef, undef,
- [$self->getNetworkFieldValue($bssid, 'SSID'), '', "networkNode,$bssid"], 5,
- $self->{'pixmap'}{$self->getNetworkPixmapName($bssid)}{'pixmap'},
- $self->{'pixmap'}{$self->getNetworkPixmapName($bssid)}{'mask'},
- $self->{'pixmap'}{$self->getNetworkPixmapName($bssid)}{'pixmap'},
- $self->{'pixmap'}{$self->getNetworkPixmapName($bssid)}{'mask'},
- $false, $false);
- $self->{'ctree'}->node_set_foreground($n, $self->getNetworkColor($bssid));
- $self->{'ctree'}->node_set_selectable($n, $true);
- if(!$self->{'ctree'}->selection())
- {
- $self->{'ctree'}->select($n);
- }
- $self->{'cnode'}{$bssid}{'node'} = $n;
- }
- # Otherwise update it
- else
- {
- my @info = $self->{'ctree'}->get_node_info($self->{'cnode'}->{$bssid}{'node'});
- $self->{'ctree'}->set_node_info($self->{'cnode'}{$bssid}{'node'},
- $self->getNetworkFieldValue($bssid, 'SSID'), 5,
- $self->{'pixmap'}{$self->getNetworkPixmapName($bssid)}{'pixmap'},
- $self->{'pixmap'}{$self->getNetworkPixmapName($bssid)}{'mask'},
- $self->{'pixmap'}{$self->getNetworkPixmapName($bssid)}{'pixmap'},
- $self->{'pixmap'}{$self->getNetworkPixmapName($bssid)}{'mask'},
- $false, $info[7]);
- $self->{'ctree'}->node_set_foreground($self->{'cnode'}{$bssid}{'node'}, $self->getNetworkColor($bssid));
- }
-
- # Loop through network fields
- for my $f ($self->{'gKismetApplication'}{'preferences'}->getPref('networkFieldNames'))
- {
- # If the field is shown
- if($self->{'gKismetApplication'}{'preferences'}->getPref('networkFieldStatus', $f))
- {
- # If the field node is not defined create it
- if(!defined $self->{'cnode'}{$bssid}{$f}{'node'})
- {
- my $n = $self->{'ctree'}->insert_node($self->{'cnode'}{$bssid}{'node'}, undef,
- [$f, $self->getNetworkFieldValue($bssid, $f), "networkNodeField,$bssid,$f"], 5,
- undef, undef, undef, undef, $true, $false);
- $self->{'ctree'}->node_set_selectable($n, $false);
- $self->{'cnode'}{$bssid}{$f}{'node'} = $n;
- }
- # Otherwise update it
- else
- {
- $self->{'ctree'}->set_text($self->{'cnode'}{$bssid}{$f}{'node'}, 1,
- $self->getNetworkFieldValue($bssid, $f));
- }
- }
- }
-
- $self->{'ctree'}->thaw();
- }
-
- #
- # Network is deleted
- #
- sub networkScreenRemove
- {
- my $self = shift;
- my $bssid = shift;
-
- if(defined $self->{'cnode'}{$bssid})
- {
- $self->{'ctree'}->remove_node($self->{'cnode'}{$bssid}{'node'});
- delete $self->{'cnode'}{$bssid};
- }
- }
-
- #
- # Client is updated or added
- #
- sub clientScreenUpdate
- {
- my $self = shift;
- my $bssid = shift;
- my $mac = shift;
-
- if(!defined $self->{'connection'})
- {
- return;
- }
-
- # If network node is not defined we can't proceed
- if(!defined $self->{'cnode'}{$bssid})
- {
- return;
- }
-
- $self->{'ctree'}->freeze();
-
- # If client node is not defined create it
- if(!defined $self->{'cnode'}{$bssid}{'client'}{$mac}{'node'})
- {
- my $n = $self->{'ctree'}->insert_node($self->{'cnode'}{$bssid}{'node'}, undef,
- [$self->getClientFieldValue($bssid, $mac, 'MAC'), '', "clientNode,$bssid,$mac"], 5,
- $self->{'pixmap'}{$self->getClientPixmapName($bssid, $mac)}{'pixmap'},
- $self->{'pixmap'}{$self->getClientPixmapName($bssid, $mac)}{'mask'},
- $self->{'pixmap'}{$self->getClientPixmapName($bssid, $mac)}{'pixmap'},
- $self->{'pixmap'}{$self->getClientPixmapName($bssid, $mac)}{'mask'},
- $false, $false);
- $self->{'cnode'}{$bssid}{'client'}{$mac}{'node'} = $n;
- $self->{'ctree'}->node_set_selectable($n, $false);
- $self->networkScreenUpdate($bssid);
- }
- # otherwise update it
- else
- {
- my @info = $self->{'ctree'}->get_node_info($self->{'cnode'}{$bssid}{'client'}{$mac}{'node'});
- $self->{'ctree'}->set_node_info($self->{'cnode'}{$bssid}{'client'}{$mac}{'node'},
- $self->getClientFieldValue($bssid, $mac, 'MAC'), 5,
- $self->{'pixmap'}{$self->getClientPixmapName($bssid, $mac)}{'pixmap'},
- $self->{'pixmap'}{$self->getClientPixmapName($bssid, $mac)}{'mask'},
- $self->{'pixmap'}{$self->getClientPixmapName($bssid, $mac)}{'pixmap'},
- $self->{'pixmap'}{$self->getClientPixmapName($bssid, $mac)}{'mask'},
- $false, $info[7]);
- }
-
- # Loop through client fields
- for my $f ($self->{'gKismetApplication'}{'preferences'}->getPref('clientFieldNames'))
- {
- # If the field is shown
- if($self->{'gKismetApplication'}{'preferences'}->getPref('clientFieldStatus', $f))
- {
- # If the client field is not defined create it
- if(!defined $self->{'cnode'}{$bssid}{'client'}{$mac}{$f}{'node'})
- {
- my $n = $self->{'ctree'}->insert_node($self->{'cnode'}{$bssid}{'client'}{$mac}{'node'}, undef,
- [$f, $self->getClientFieldValue( $bssid, $mac, $f), "clientNodeField,$bssid,$mac,$f"], 5,
- undef, undef, undef, undef, $true, $false);
- $self->{'cnode'}{$bssid}{'client'}{$mac}{$f}{'node'} = $n;
- $self->{'ctree'}->node_set_selectable($n, $false);
- }
- # otherwise update it
- else
- {
- $self->{'ctree'}->set_text($self->{'cnode'}{$bssid}{'client'}{$mac}{$f}{'node'}, 1,
- $self->getClientFieldValue($bssid, $mac, $f));
- }
- }
- }
-
- $self->{'ctree'}->thaw();
- }
-
- #
- # Get colors
- #
- sub buildColors
- {
- my $self = shift;
- my $colormap = $self->{'ctree'}->get_colormap();
-
- my $colorYellow = Gtk::Gdk::Color->parse_color("gold3");
- $colorYellow = $colormap->color_alloc($colorYellow);
- $self->{'colorYellow'} = $colorYellow;
-
- my $colorGreen = Gtk::Gdk::Color->parse_color("green3");
- $colorGreen = $colormap->color_alloc($colorGreen);
- $self->{'colorGreen'} = $colorGreen;
-
- my $colorRed = Gtk::Gdk::Color->parse_color("red2");
- $colorRed = $colormap->color_alloc($colorRed);
- $self->{'colorRed'} = $colorRed;
-
- my $colorBlack = Gtk::Gdk::Color->parse_color("black");
- $colorBlack = $colormap->color_alloc($colorBlack);
- $self->{'colorBlack'} = $colorBlack;
- }
-
- #
- # Collapse selected nodes
- #
- sub collapse
- {
- my $self = shift;
- my (@selection) = $self->{'ctree'}->selection();
- for my $selected (@selection)
- {
- $self->{'ctree'}->collapse_recursive($selected);
- }
- }
-
- #
- # Expand selected nodes
- #
- sub expand
- {
- my $self = shift;
- my (@selection) = $self->{'ctree'}->selection();
- for my $selected (@selection)
- {
- $self->{'ctree'}->expand_recursive($selected);
- }
- }
-
- #
- # Get selected network bssid
- #
- sub getSelectedNetworks
- {
- my $self = shift;
- my (@selection) = $self->{'ctree'}->selection();
- my @networks;
- for my $selected (@selection)
- {
- my $data = $self->{'ctree'}->node_get_text($selected, 2);
- my @fields = split /,/, $data;
- if($fields[0] eq 'networkNode')
- {
- push @networks, $fields[1];
- }
- }
- return @networks;
- }
-
- #
- # Return printable network data
- #
- sub getNetworkFieldValue
- {
- my $self = shift;
- my $bssid = shift;
- my $field = shift;
-
- if(!defined $self->{'connection'})
- {
- return undef;
- }
- my $network = $self->{'connection'}->getNetwork();
-
- if($field eq 'SSID')
- {
- my $ssid = $network->{$bssid}{'ssid'};
- if($network->{$bssid}{'cloaked'})
- {
- $ssid = '<' . $ssid . '>';
- }
- return $ssid;
- }
- elsif($field eq 'BSSID')
- {
- return $network->{$bssid}{'bssid'};
- }
- elsif($field eq 'Beacon info')
- {
- return $network->{$bssid}{'beaconinfo'};
- }
- elsif($field eq 'Carrier')
- {
- if($network->{$bssid}{'carrierset'} & (1 << $carrier_type{'carrier_unknown'}))
- {
- return 'Unknown';
- }
- elsif($network->{$bssid}{'carrierset'} & (1 << $carrier_type{'carrier_80211b'}))
- {
- return 'IEEE 802.11b';
- }
- elsif($network->{$bssid}{'carrierset'} & (1 << $carrier_type{'carrier_80211bplus'}))
- {
- return 'IEEE 802.11b+';
- }
- elsif($network->{$bssid}{'carrierset'} & (1 << $carrier_type{'carrier_80211a'}))
- {
- return 'IEEE 802.11a';
- }
- elsif($network->{$bssid}{'carrierset'} & (1 << $carrier_type{'carrier_80211g'}))
- {
- return 'IEEE 802.11g';
- }
- elsif($network->{$bssid}{'carrierset'} & (1 << $carrier_type{'carrier_80211fhss'}))
- {
- return 'IEEE 802.11 FHSS';
- }
- elsif($network->{$bssid}{'carrierset'} & (1 << $carrier_type{'carrier_80211dsss'}))
- {
- return 'IEEE 802.11 DSSS';
- }
- else
- {
- return 'Unknown';
- }
- }
- elsif($field eq 'Encoding')
- {
- if($network->{$bssid}{'encodingset'} & (1 << $encoding_type{'encoding_unknown'}))
- {
- return 'Unknown';
- }
- elsif($network->{$bssid}{'encodingset'} & (1 << $encoding_type{'encoding_cck'}))
- {
- return 'CCK';
- }
- elsif($network->{$bssid}{'encodingset'} & (1 << $encoding_type{'encoding_pbcc'}))
- {
- return 'PBCC';
- }
- elsif($network->{$bssid}{'encodingset'} & (1 << $encoding_type{'encoding_ofdm'}))
- {
- return 'OFDM';
- }
- else
- {
- return 'Unknown';
- }
- }
- elsif($field eq 'Manufacturer')
- {
- my($manuf, $model, $score) = $self->lookupManuf(
- $network->{$bssid}{'type'} == $network_type{'network_adhoc'} || $network->{$bssid}{'type'} == $network_type{'network_probe'} ?
- $self->{'clManuf'} : $self->{'apManuf'},
- $bssid, $network->{$bssid}{'ssid'}, $network->{$bssid}{'channel'}, $network->{$bssid}{'wep'}, $network->{$bssid}{'cloaked'},
- $network->{$bssid}{'rangeip'});
- return($manuf);
- }
- elsif($field eq 'Model')
- {
- my($manuf, $model, $score) = $self->lookupManuf(
- $network->{$bssid}{'type'} == $network_type{'network_adhoc'} || $network->{$bssid}{'type'} == $network_type{'network_probe'} ?
- $self->{'clManuf'} : $self->{'apManuf'},
- $bssid, $network->{$bssid}{'ssid'}, $network->{$bssid}{'channel'}, $network->{$bssid}{'wep'}, $network->{$bssid}{'cloaked'},
- $network->{$bssid}{'rangeip'});
- return($model);
- }
- elsif($field eq 'Max rate')
- {
- return $network->{$bssid}{'maxrate'};
- }
- elsif($field eq "Max seen")
- {
- return $network->{$bssid}{'maxseenrate'} * 100;
- }
- elsif($field eq 'First seen')
- {
- return scalar localtime($network->{$bssid}{'firsttime'});
- }
- elsif($field eq 'Last seen')
- {
- return scalar localtime($network->{$bssid}{'lasttime'});
- }
- elsif($field eq 'Clients')
- {
- my @clients = keys %{$network->{$bssid}{'client'}};
- return $#{clients} + 1;
- }
- elsif($field eq 'Type')
- {
- if($network->{$bssid}{'type'} == $network_type{'network_ap'})
- {
- return 'Access Point (infrastructure)';
- }
- elsif($network->{$bssid}{'type'} == $network_type{'network_adhoc'})
- {
- return 'Ad-hoc';
- }
- elsif($network->{$bssid}{'type'} == $network_type{'network_probe'})
- {
- return 'Probe request (searching client)';
- }
- elsif($network->{$bssid}{'type'} == $network_type{'network_turbocell'})
- {
- return 'Turbocell';
- }
- elsif($network->{$bssid}{'type'} == $network_type{'network_data'})
- {
- return 'Data (no network control traffic)';
- }
- elsif($network->{$bssid}{'type'} == $network_type{'network_remove'})
- {
- return 'Network remove request';
- }
- }
- elsif($field eq 'Channel')
- {
- return $network->{$bssid}{'channel'};
- }
- elsif($field eq 'WEP')
- {
- $network->{$bssid}{'wep'} ? return 'Yes' : return 'No';
- }
- elsif($field eq 'Encryption')
- {
- if($network->{$bssid}{'wep'} == $encryption_type{'encryption_none'})
- {
- return 'None';
- }
-
- my $res = '';
- if($network->{$bssid}{'wep'} & $encryption_type{'encryption_unknown'})
- {
- $res .= 'Unknown ';
- }
- if($network->{$bssid}{'wep'} & $encryption_type{'encryption_wep'})
- {
- $res .= 'WEP ';
- }
- if($network->{$bssid}{'wep'} & $encryption_type{'encryption_layer3'})
- {
- $res .= 'Layer 3 ';
- }
- if($network->{$bssid}{'wep'} & $encryption_type{'encryption_wpa'})
- {
- $res .= 'WPA ';
- }
- if($network->{$bssid}{'wep'} & $encryption_type{'encryption_leap'})
- {
- $res .= 'LEAP ';
- }
- if($network->{$bssid}{'wep'} & $encryption_type{'encryption_ttls'})
- {
- $res .= 'TTLS ';
- }
- if($network->{$bssid}{'wep'} & $encryption_type{'encryption_tls'})
- {
- $res .= 'TLS ';
- }
- if($network->{$bssid}{'wep'} & $encryption_type{'encryption_peap'})
- {
- $res .= 'PEAP ';
- }
- if($network->{$bssid}{'wep'} & $encryption_type{'encryption_isakmp'})
- {
- $res .= 'ISAKMP ';
- }
- if($network->{$bssid}{'wep'} & $encryption_type{'encryption_pptp'})
- {
- $res .= 'PPTP ';
- }
- return substr($res, 0, -1);
- }
- elsif($field eq "Decrypted")
- {
- return $network->{$bssid}{'decrypted'} ? 'Yes' : 'No';
- }
- elsif($field eq 'Beacon')
- {
- return $network->{$bssid}{'beaconrate'};
- }
- elsif($field eq 'Data packets')
- {
- return $network->{$bssid}{'datapackets'};
- }
- elsif($field eq 'LLC packets')
- {
- return $network->{$bssid}{'llcpackets'};
- }
- elsif($field eq 'Crypt packets')
- {
- return $network->{$bssid}{'cryptpackets'};
- }
- elsif($field eq 'Weak packets')
- {
- return $network->{$bssid}{'weakpackets'};
- }
- elsif($field eq 'Dupe IV')
- {
- return $network->{$bssid}{'dupeivpackets'};
- }
- elsif($field eq 'Data')
- {
- return $network->{$bssid}{'datasize'} . " bytes";
- }
- elsif($field eq 'Power')
- {
- return $network->{$bssid}{'signal'} . "/" . $network->{$bssid}{'bestsignal'};
- }
- elsif($field eq 'Noise')
- {
- return $network->{$bssid}{'noise'} . "/" . $network->{$bssid}{'bestnoise'};
- }
- elsif($field eq 'IP Range')
- {
- return $network->{$bssid}{'rangeip'};
- }
- elsif($field eq 'IP Type')
- {
- if($network->{$bssid}{'atype'} == $address_type{'address_none'})
- {
- return 'None detected';
- }
- elsif($network->{$bssid}{'atype'} == $address_type{'address_factory'})
- {
- return 'Factory default';
- }
- elsif($network->{$bssid}{'atype'} == $address_type{'address_udp'})
- {
- return 'UDP (' . $network->{$bssid}{'octets'} . " octets)";
- }
- elsif($network->{$bssid}{'atype'} == $address_type{'address_arp'})
- {
- return 'ARP (' . $network->{$bssid}{'octets'} . " octets)";
- }
- elsif($network->{$bssid}{'atype'} == $address_type{'address_tcp'})
- {
- return 'TCP (' . $network->{$bssid}{'octets'} . " octets)";
- }
- elsif($network->{$bssid}{'atype'} == $address_type{'address_dhcp'})
- {
- return 'DHCP';
- }
- elsif($network->{$bssid}{'atype'} == $address_type{'address_group'})
- {
- return 'Group (aggregate)';
- }
- else
- {
- return 'UNKNOWN';
- }
- }
- else
- {
- return('Not implemented');
- }
- }
-
- #
- # Return printable client data
- #
- sub getClientFieldValue
- {
- my $self = shift;
- my $bssid = shift;
- my $mac = shift;
- my $field = shift;
-
- if(!defined $self->{'connection'})
- {
- return undef;
- }
- my $network = $self->{'connection'}->getNetwork();
-
- if($field eq 'MAC')
- {
- return $network->{$bssid}{'client'}{$mac}{'mac'};
- }
- elsif($field eq 'Type')
- {
- if($network->{$bssid}{'client'}{$mac}{'type'} == $client_type{'client_unknown'})
- {
- return 'Unknown';
- }
- elsif ($network->{$bssid}{'client'}{$mac}{'type'} == $client_type{'client_fromds'})
- {
- return 'From Distribution (AP->Wireless)';
- }
- elsif ($network->{$bssid}{'client'}{$mac}{'type'} == $client_type{'client_tods'})
- {
- return 'To Distribution (Wireless->AP)';
- }
- elsif ($network->{$bssid}{'client'}{$mac}{'type'} == $client_type{'client_interds'})
- {
- return 'Intra-distribution (AP->AP)';
- }
- elsif ($network->{$bssid}{'client'}{$mac}{'type'} == $client_type{'client_established'})
- {
- return 'Established (Wireless->AP and AP->Wireless)';
- }
- else
- {
- return 'Unknown';
- }
- }
- elsif($field eq 'Manufacturer')
- {
- my($manuf, $model, $score) = $self->lookupManuf($self->{'clManuf'}, $mac, $network->{$bssid}{'ssid'},
- $network->{$bssid}{'channel'}, $network->{$bssid}{'wep'}, $network->{$bssid}{'cloaked'}, $network->{$bssid}{'client'}{$mac}{'ip'});
- return($manuf);
- }
- elsif($field eq 'Model')
- {
- my($manuf, $model, $score) = $self->lookupManuf($self->{'clManuf'}, $mac, $network->{$bssid}{'ssid'},
- $network->{$bssid}{'channel'}, $network->{$bssid}{'wep'}, $network->{$bssid}{'cloaked'}, $network->{$bssid}{'client'}{$mac}{'ip'});
- return($model);
- }
- elsif($field eq 'First seen')
- {
- return scalar localtime $network->{$bssid}{'client'}{$mac}{'firsttime'};
- }
- elsif($field eq 'Last seen')
- {
- return scalar localtime $network->{$bssid}{'client'}{$mac}{'lasttime'};
- }
- elsif($field eq 'Max rate')
- {
- return $network->{$bssid}{'client'}{$mac}{'maxrate'};
- }
- elsif($field eq "Max seen")
- {
- return $network->{$bssid}{'client'}{$mac}{'maxseenrate'} * 100;
- }
- elsif($field eq 'Encoding')
- {
- if($network->{$bssid}{'client'}{$mac}{'encodingset'} & (1 << $encoding_type{'encoding_unknown'}))
- {
- return 'Unknown';
- }
- elsif($network->{$bssid}{'client'}{$mac}{'encodingset'} & (1 << $encoding_type{'encoding_cck'}))
- {
- return 'CCK';
- }
- elsif($network->{$bssid}{'client'}{$mac}{'encodingset'} & (1 << $encoding_type{'encoding_pbcc'}))
- {
- return 'PBCC';
- }
- elsif($network->{$bssid}{'client'}{$mac}{'encodingset'} & (1 << $encoding_type{'encoding_ofdm'}))
- {
- return 'OFDM';
- }
- else
- {
- return 'Unknown';
- }
- }
- elsif($field eq 'Channel')
- {
- return $network->{$bssid}{'channel'};
- }
- elsif($field eq 'WEP')
- {
- $network->{$bssid}{'client'}{$mac}{'wep'} ? return 'Yes' : return 'No';
- }
- elsif($field eq "Decrypted")
- {
- return $network->{$bssid}{'client'}{$mac}{'decrypted'} ? 'Yes' : 'No';
- }
- elsif($field eq 'IP')
- {
- $network->{$bssid}{'client'}{$mac}{'ip'};
- }
- elsif($field eq 'Data packets')
- {
- $network->{$bssid}{'client'}{$mac}{'datapackets'};
- }
- elsif($field eq 'Crypt packets')
- {
- $network->{$bssid}{'client'}{$mac}{'cryptpackets'};
- }
- elsif($field eq 'Weak packets')
- {
- $network->{$bssid}{'client'}{$mac}{'weakpackets'};
- }
- elsif($field eq 'Data')
- {
- $network->{$bssid}{'client'}{$mac}{'datasize'} . " bytes";
- }
- elsif($field eq 'Power')
- {
- return $network->{$bssid}{'client'}{$mac}{'signal'} . "/" . $network->{$bssid}{'client'}{$mac}{'bestsignal'};
- }
- elsif($field eq 'Noise')
- {
- return $network->{$bssid}{'client'}{$mac}{'noise'} . "/" . $network->{$bssid}{'client'}{$mac}{'bestnoise'};
- }
- else
- {
- return('Not implemented');
- }
- }
-
- #
- # Return color for a network
- #
- sub getNetworkColor
- {
- my $self = shift;
- my $bssid = shift;
-
- if(!defined $self->{'connection'})
- {
- return undef;
- }
- my $network = $self->{'connection'}->getNetwork();
-
- if(!$network->{$bssid}{'wep'})
- {
- my($manuf, $model, $score) = $self->lookupManuf($self->{'apManuf'}, $bssid, $network->{$bssid}{'ssid'},
- $network->{$bssid}{'channel'}, $network->{$bssid}{'wep'}, $network->{$bssid}{'cloaked'}, $network->{$bssid}{'rangeip'});
- if($score == $max_manuf_score)
- {
- return($self->{'colorRed'});
- }
- return($self->{'colorYellow'});
- }
- else
- {
- return($self->{'colorGreen'});
- }
- }
-
- #
- # Get network pixmap
- #
- sub getNetworkPixmapName
- {
- my $self = shift;
- my $bssid = shift;
-
- if(!defined $self->{'connection'})
- {
- return undef;
- }
- my $network = $self->{'connection'}->getNetwork();
-
- $self->buildPixmaps();
- my $pixmapName;
-
- if($network->{$bssid}{'type'} == $network_type{'network_ap'})
- {
- $pixmapName = 'networkAP';
- }
- elsif($network->{$bssid}{'type'} == $network_type{'network_adhoc'})
- {
- $pixmapName = 'networkAdhoc';
- }
- elsif($network->{$bssid}{'type'} == $network_type{'network_probe'})
- {
- $pixmapName = 'networkProbe';
- }
- elsif($network->{$bssid}{'type'} == $network_type{'network_turbocell'})
- {
- $pixmapName = 'networkTurbocell';
- }
- elsif($network->{$bssid}{'type'} == $network_type{'network_data'})
- {
- $pixmapName = 'networkData';
- }
- elsif($network->{$bssid}{'type'} == $network_type{'network_remove'})
- {
- $pixmapName = 'networkRemove';
- }
-
- if(time() - $network->{$bssid}{'lasttime'} < $activeTimeout)
- {
- $pixmapName .= 'Active';
- }
-
- return $pixmapName;
- }
-
- #
- # Get client pixmap
- #
- sub getClientPixmapName
- {
- my $self = shift;
- my $bssid = shift;
- my $mac = shift;
-
- if(!defined $self->{'connection'})
- {
- return undef;
- }
- my $network = $self->{'connection'}->getNetwork();
-
- $self->buildPixmaps();
- my $pixmapName;
-
- if($network->{$bssid}{'client'}{$mac}{'type'} == $client_type{'client_unknown'})
- {
- $pixmapName = 'clientUnknown';
- }
- elsif ($network->{$bssid}{'client'}{$mac}{'type'} == $client_type{'client_fromds'})
- {
- $pixmapName = 'clientFromDist';
- }
- elsif ($network->{$bssid}{'client'}{$mac}{'type'} == $client_type{'client_tods'})
- {
- $pixmapName = 'clientToDist';
- }
- elsif ($network->{$bssid}{'client'}{$mac}{'type'} == $client_type{'client_interds'})
- {
- $pixmapName = 'clientIntraDist';
- }
- elsif ($network->{$bssid}{'client'}{$mac}{'type'} == $client_type{'client_established'})
- {
- $pixmapName = 'clientEstablished';
- }
-
- if(time() - $network->{$bssid}{'client'}{$mac}{'lasttime'} < $activeTimeout)
- {
- $pixmapName .= 'Active';
- }
-
- return $pixmapName;
- }
-
- #
- # Build pixmaps if not yet built
- #
- sub buildPixmaps
- {
- my $self = shift;
- if(!$self->{'pixmapsBuilt'})
- {
- for my $pixmap (qw(networkAP networkAdhoc networkProbe networkTurbocell networkData networkRemove
- clientFromDist clientToDist clientIntraDist clientEstablished clientUnknown
- networkAPActive networkAdhocActive networkProbeActive networkTurbocellActive networkDataActive networkRemoveActive
- clientFromDistActive clientToDistActive clientIntraDistActive clientEstablishedActive clientUnknownActive))
- {
- ($self->{'pixmap'}{$pixmap}{'pixmap'}, $self->{'pixmap'}{$pixmap}{'mask'}) =
- Gtk::Gdk::Pixmap->create_from_xpm($self->{'ctree'}->window(),
- Gtk::Widget->get_default_style()->bg('normal'),
- $self->{'gKismetApplication'}{'path'}{'xpm'} . '/' . $pixmap . '.xpm');
- }
- $self->{'pixmapsBuilt'} = $true;
- }
- }
-
- 1;
-